package com.doubao.user.security;

import com.doubao.user.entity.User;
import com.doubao.user.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;

/**
 * 用户认证拦截器，从请求头中获取用户ID
 */
@Component
@Slf4j
public class UserAuthInterceptor implements HandlerInterceptor {

    private static final String USER_ID_HEADER = "X-User-ID";

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 清理上下文以确保不会有残留的用户ID
        UserContext.clear();

        // 记录所有请求头，用于调试
        log.debug("===== 请求头信息 =====");
        java.util.Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            log.debug("{}: {}", headerName, request.getHeader(headerName));
        }

        // 先尝试从网关传递的X-User-ID头获取用户ID
        String userIdStr = request.getHeader(USER_ID_HEADER);
        if (StringUtils.hasText(userIdStr)) {
            try {
                Long userId = Long.valueOf(userIdStr);
                UserContext.setUserId(userId);
                log.debug("从X-User-ID头提取用户ID: {}", userId);
                return true;
            } catch (NumberFormatException e) {
                log.error("无法解析X-User-ID: {}", userIdStr, e);
            }
        }

        // 如果X-User-ID头不存在，尝试从JWT令牌中提取用户信息
        String authorization = request.getHeader("Authorization");
        if (StringUtils.hasText(authorization) && authorization.startsWith("Bearer ")) {
            String token = authorization.substring(7);
            try {
                // 使用与网关相同的密钥和方法解析JWT
                String SECRET_KEY = "DoubaoAuthServiceJwtSecretKey0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                SecretKey jwtSecretKey = Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));

                Claims claims = Jwts.parserBuilder()
                        .setSigningKey(jwtSecretKey)
                        .build()
                        .parseClaimsJws(token)
                        .getBody();

                // 解析成功后，将 Token 存储到 UserContext
                UserContext.setToken(token);
                log.debug("JWT解析成功，Token已存入UserContext");

                // 从令牌的sub字段获取用户名
                String username = claims.getSubject();
                log.debug("从JWT令牌解析出用户名: {}", username);

                // 如果令牌中包含userId字段，直接使用
                if (claims.get("userId") != null) {
                    String userId = claims.get("userId", String.class);
                    UserContext.setUserId(Long.valueOf(userId));
                    log.debug("从JWT令牌claims中提取用户ID: {}", userId);
                }
                // 如果没有userId字段，通过用户名查询用户ID
                else if (username != null) {
                    try {
                        // 通过用户名查询用户信息
                        User user = userService.getUserByUsername(username);
                        if (user != null) {
                            UserContext.setUserId(user.getId());
                            log.debug("从数据库通过用户名查询到用户ID: {}", user.getId());
                        } else {
                            // 如果用户不存在，记录日志但仍允许请求通过
                            log.warn("数据库中未找到用户名为{}的用户", username);

                            // 尝试从用户名中提取ID作为备用方案
                            if (username.startsWith("user_")) {
                                try {
                                    String userIdPart = username.substring(5); // 移除"user_"前缀
                                    Long userId = Long.valueOf(userIdPart);
                                    log.debug("备用方案：从用户名提取用户ID: {}", userId);

                                    // 注意：这里应该谨慎使用，因为这种方法不可靠
                                    // 在开发/测试环境可以使用，但生产环境应确保用户数据一致性
                                    UserContext.setUserId(userId);
                                } catch (Exception e) {
                                    log.error("无法从用户名提取用户ID: {}", username, e);
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("查询用户信息失败: {}", e.getMessage(), e);
                    }
                }
            } catch (Exception e) {
                log.error("JWT令牌解析失败: {}", e.getMessage(), e);
                // 解析失败时，清除可能已设置的无效Token
                UserContext.clear();
            }
        } else {
            log.warn("Authorization header missing or not Bearer type.");
        }

        // 总是允许请求通过，具体接口会根据需要检查认证状态
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求结束后清理上下文
        UserContext.clear();
    }
}